home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 5 / MacMania 5.toast / / Tools&Utilities / Digester 2.3 / sources / digester.c next >
Encoding:
C/C++ Source or Header  |  1996-05-14  |  42.2 KB  |  1,910 lines  |  [TEXT/EDIT]

  1. /*     file: digester2.3.c
  2.         purpose:    digest e-mails from info-mac digest into HTML format
  3.         author:        Andre' C. van der Ham
  4.         e-mail:        A.C.vanderHam@ET.TUDelft.NL
  5.     
  6.         notice:        Don't forget to set the path to your scripts directory
  7.             
  8.         for THINK C users:
  9.         project profile:
  10.             segment 1:     digester
  11.                         MacTraps
  12.             segment 2:    ANSI
  13.                         unix
  14.                         
  15.         project type:    size:     200K
  16.                         flags:    0080    32-bit compatibility
  17.                             
  18.         You had better also delete all the num_args and arg_strings stuff in main.
  19.         So, 'int main( void )'.
  20.         
  21. */
  22.  
  23. /* includes */
  24.  
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #ifdef __THINK__
  29. #include <Files.h>
  30. #include <console.h>
  31. #include <StandardFile.h>
  32. #endif
  33.  
  34. #define    LINELENGTH    80
  35. #define    DRE            "http://lcewww.et.tudelft.nl/people/vdham/vdham.html"
  36. #define    PARMS        "digester.par"
  37. #define    DIGESTER    "Digester 2.3"
  38. #define    DIGWHERE    "http://lcewww.et.tudelft.nl/people/vdham/info-mac/"
  39. #define    notify        printf
  40.  
  41. int    debug=0;
  42.  
  43. FILE    *outTPrg, *outTMes, *outPrg, *outMes, *inP;
  44.  
  45. typedef struct Pars
  46. {
  47.     char    adLink[80];            /* link to ad */
  48.     char    adImage[80];        /* link to image */
  49.     int        adOn;                /* boolean if ad feature is on */
  50.     
  51.     char    scriptPath[80];        /* path to mail script */
  52.     char    imagePath[80];        /* path to images of buttons */
  53.     char    sitesFile[20];        /* path to sites file */
  54.     char    destPath[80];        /* additional path for destination files */
  55.     char    Ftype[10];            /* finder type */
  56.     char    Fcreator[10];        /* finder creator */
  57.     
  58.     char    DigestName[20];        /* name of the original digest file */
  59.     char    nameAll[20];        /* name of the complete HTML digest file */
  60.     char    nameTOC[20];        /* name of the toc only file */
  61.     char    nameProg[20];        /* name of the programs file (either with or without toc) */
  62.     char    nameMess[20];        /* name of the messages file (either with or without toc) */
  63.     
  64.     char    BegOfDigest[80];    /* begin of digest text */
  65.     char    Volume[80];            /* volume number prefix */
  66.     char    Issue[80];            /* issue number prefix */
  67.     char    Date[20];            /* date text prefix */
  68.     
  69.     char    EndOfDigest[80];    /* end of digest text */
  70.     char    BeginOfTopics[80];    /* begin of topics text */
  71.     char    EndOfTopics[80];    /* end of topics text */
  72.     char    EndOfMessage[80];    /* end of message text */
  73.     
  74.     char    RootPath[20];        /* begin of root directory of mirror */
  75.     char    BegOfFile[40];        /* begin of file path */
  76.     char    EndOfFile[20];        /* end of file path */
  77.     
  78.     int        Type;                /* type of digest */
  79.     int        Buttons;            /* buttons on/off */
  80.     int        Mail;                /* mail button on/off */
  81.     int        Files;                /* archive files link on/off */
  82.     int        URLs;                /* URL link on/off */
  83.     int        MURLs;                /* mail URLs on/off */
  84.  
  85.     char    *sites;                /* pointer to array of strings of mirror sites */
  86.     int        nSites;                /* number of sites in array */
  87.     
  88.     char    mFrom[20];            /* e-mail from */
  89.     char    mTo[20];            /*            to */
  90.     char    mDate[20];            /*           date */
  91.     char    mSubject[20];        /*       subject */
  92. } *ParsP;
  93.  
  94.  
  95. typedef struct Vars
  96. {
  97.     char     whichFile[512];
  98.     int        VolNum;
  99.     int        Issue;
  100.     int        itemCount;
  101.     char    header[100];    /* header of digest */
  102.  
  103.     char    nameAll[20];        /* name of the complete digest file */
  104.     char    nameTOC[20];        /* name of the toc only file */
  105.     char    nameProg[20];        /* name of the programs file (either with or without toc) */
  106.     char    nameMess[20];        /* name of the messages file (either with or without toc) */
  107.     
  108. } *VarsP;
  109.  
  110.  
  111. #ifdef __THINK__
  112.  
  113. /**********************************
  114.  
  115.     Mac specific file get function
  116.     
  117. */
  118.  
  119. int GetName( char *name )
  120. {
  121.     SFReply        theReply;
  122.     Point        where;
  123.     SFTypeList    typeList;
  124.  
  125.     typeList[0]='TEXT';            /* file type to search for */
  126.     where.h=20;  where.v=90;    /* SF dialog window position */
  127.  
  128.     SFGetFile(where,0,0L,1,typeList,NULL,&theReply);
  129.  
  130.     if ( theReply.good == TRUE ) 
  131.     { 
  132.         strncpy( name, (char *)(theReply.fName+1), theReply.fName[0] );
  133.         name[theReply.fName[0]]=0;
  134.         return(1);
  135.     }
  136.     else
  137.         return(0);
  138. }
  139.  
  140. #endif
  141.  
  142. /**********************************
  143.  
  144.     Find the DIGEST header and fill-in the volume and issue numbers
  145.     also the header is copied for future use
  146.     
  147. */
  148.  
  149. int findHeader( ParsP p, VarsP v, char *line, int parse )
  150. {
  151.     char    *cptr;
  152.     int    found=0;
  153.     
  154.     /* init header vars */
  155.     
  156.     if(parse)
  157.     {
  158.         v->VolNum=0;
  159.         v->Issue=0;
  160.     }
  161.     
  162.     /* while there is still a line to read find header */
  163.     
  164.     do {    
  165.             if( feof( inP ) )
  166.             {
  167.                 notify("End of file reached.\n");
  168.                 notify("Could not find Begin of Digest (BOD) tag.\n");
  169.                 notify("Closing file ...\n");
  170.                 return(0);
  171.             }
  172.             
  173.             /* check if the line is not empty */
  174.             
  175.             if( fgets( line, 256, inP ) != NULL )
  176.             {
  177.                 /* check for the begin of digest string */
  178.                 
  179.                 if( strncmp( line, p->BegOfDigest, strlen(p->BegOfDigest) ) == 0 )
  180.                 {
  181.                     notify("Found %s\n", p->BegOfDigest);
  182.                     notify(line);
  183.                     
  184.                     strcpy( v->header, line );            /* make a copy for use as heading */
  185.                     
  186.                     found = 1;
  187.                     
  188.                     /* extract volume number */
  189.                     
  190.                     if( parse )
  191.                     {
  192.                         if( p->Volume!=NULL )
  193.                         {
  194.                             if( strlen(p->Volume)>0 )
  195.                             {
  196.                                 cptr = (char *)strstr( line, p->Volume );
  197.                                 if( cptr==NULL )
  198.                                 {
  199.                                     notify("Can't find volume number\n");
  200.                                     notify("Please specify Volume number: ");
  201.                                     scanf("%d", &(v->VolNum));
  202.                                 }
  203.                                 else
  204.                                     v->VolNum = atoi( cptr+strlen(p->Volume) );
  205.                             }
  206.                         }
  207.                         
  208.                         /* extract issue number */
  209.                         
  210.                         if( p->Issue!=NULL )
  211.                         {
  212.                             if( strlen(p->Issue)>0 )
  213.                             {
  214.                                 cptr = (char *)strstr( line, p->Issue );
  215.                                 if( cptr==NULL )
  216.                                 {
  217.                                     notify("Can't find issue number\n");
  218.                                     notify("Please specify Issue number: ");
  219.                                     scanf("%d", &(v->Issue));
  220.                                 }
  221.                                 else
  222.                                     v->Issue = atoi( cptr+strlen(p->Issue) );
  223.                             }
  224.                             else
  225.                             {
  226.                                 notify("Please specify Issue number: ");
  227.                                 scanf("%d", &(v->Issue));
  228.                             }
  229.                         }    
  230.                     }
  231.                 }
  232.             }
  233.     } while( !found );
  234.     
  235.     return(1);
  236. }
  237.  
  238. void GetDestName( char *format, VarsP v, char *name, char *path, char *comment )
  239. {
  240.     char    dummy[200];
  241.     
  242.     if( (v->Issue!=0) && (v->VolNum!=0) )
  243.     {
  244.         sprintf(name, format, v->Issue, v->VolNum );
  245.     }
  246.     else if( (v->Issue!=0 ) )
  247.     {
  248.         sprintf(name, format, v->Issue );
  249.     }
  250.     else
  251.     {
  252.         notify( comment );
  253.         fgets(name,38,stdin);
  254.         
  255.         if( strlen(name)<1 )
  256.         {
  257.             notify("Illegal file name!\n");
  258.             strcpy( name, "digest.html");
  259.             notify("Using default ");
  260.         }
  261.     }
  262.     
  263.     strcat(path, name);
  264.     notify("name = '%s'\n", path);
  265. }
  266.  
  267. #ifdef __THINK__
  268.                 
  269. void SetupFinderInfo( char *name, OSType type, OSType creator, char *path )
  270. {
  271.     char    fileN[200];
  272.     Str255     fileName;
  273.     FInfo    fndrInfo;
  274.     
  275.     strcpy( fileN, path );
  276.     strcat( fileN, name );
  277.     
  278.     notify("Setting up finder info for '%s'.\n", fileN);
  279.     
  280.     strncpy( (char *)fileName+1, fileN, strlen(fileN) );
  281.     
  282.     fileName[0] = strlen(fileN);
  283.     
  284.     if( GetFInfo(fileName,0,&fndrInfo)==0 )
  285.     {
  286.         fndrInfo.fdType = type;
  287.         fndrInfo.fdCreator = creator;
  288.         if( SetFInfo(fileName, 0, &fndrInfo)!=0 )
  289.         {
  290.             notify("OS error setting finder info.\n");
  291.         }
  292.     }
  293.     else
  294.     {
  295.         notify("Couldn't set type creator due to OS error.\n");
  296.     }
  297. }
  298.  
  299. void SetUpAllFinderInfo( ParsP p, VarsP v )
  300. {
  301.     OSType     type, creator;
  302.     int        i;
  303.     OSType     k, test;
  304.     
  305.     
  306.     if( (strlen(p->Ftype)<4) || (strlen(p->Fcreator)<4) )
  307.     {
  308.         notify("Illegal type (FTYPE) and creator (FCREAT) specified.\n");
  309.         notify("Type and creator parameters should be 4 characters long.\n");
  310.         notify("Please, check your parameters file.\n");
  311.         return;
  312.     }
  313.     
  314.     k=1;
  315.     type=0;
  316.     creator=0;
  317.     
  318.     test=255;
  319.     
  320.     if( (char)test!=255 )    /* if little endian */
  321.     {    
  322.         notify("You have a Little Endian processor. Great, so what! Just checking.\n");
  323.  
  324.         for(i=0; i<4; i++)
  325.         {
  326.             type+=(OSType)(p->Ftype[3-i])*k;    
  327.             creator+=(OSType)(p->Fcreator[3-i])*k;
  328.             if(i<3) k *= 256;
  329.         }
  330.     }
  331.     else
  332.     {
  333.         notify("You have a Big Endian processor. Great, so what! Just checking.\n");
  334.  
  335.         for(i=0; i<4; i++)
  336.         {
  337.             type+=(OSType)(p->Ftype[i])*k;    
  338.             creator+=(OSType)(p->Fcreator[i])*k;
  339.             if(i<3) k *= 256;
  340.         }
  341.     }
  342.  
  343.     notify("Type: '%s', Creator '%s'.\n", p->Ftype, p->Fcreator);
  344.  
  345.     switch( p->Type )                        
  346.     {
  347.         case 1:        /* type 1: the entire digest in 1 file */
  348.         
  349.                 SetupFinderInfo( v->nameAll, type, creator, p->destPath );
  350.         break;
  351.         
  352.         case 2:        /* type 2: topics, programs and messages as separate files */
  353.         
  354.                 SetupFinderInfo( v->nameTOC, type, creator, p->destPath );
  355.                 if( p->Files )
  356.                 {
  357.                     SetupFinderInfo( v->nameProg, type, creator, p->destPath );
  358.                 }
  359.                 SetupFinderInfo( v->nameMess, type, creator, p->destPath );
  360.         break;
  361.         
  362.         case 3:        /* type 3: toc + progs, toc + mes */
  363.         
  364.                 /* toc + progs files */
  365.                 
  366.                 if( p->Files )
  367.                 {
  368.                     SetupFinderInfo( v->nameProg, type, creator, p->destPath );
  369.                 }
  370.                 
  371.                 SetupFinderInfo( v->nameMess, type, creator, p->destPath );
  372.         break;
  373.     }
  374.  
  375. }
  376.  
  377. #endif
  378.  
  379.  
  380.  
  381. int SetUpFiles( ParsP p, VarsP v )
  382. {
  383.     char    name[200];
  384.     
  385.     /* set-up output files */
  386.     
  387.     switch( p->Type )                        
  388.     {
  389.         case 1:        /* type 1: the entire digest in 1 file */
  390.         
  391.                 notify("Type 1:\n");
  392.                 
  393.                 strcpy( name, p->destPath );
  394.                 GetDestName( p->nameAll, v, v->nameAll, name,
  395.                             "Please specify destination file name for entire digest: " );
  396.                 
  397.                 if( (outTMes = fopen( name,"w")) == NULL )
  398.                 {
  399.                     notify( "Can't open '%s'\n", name );
  400.                     return(0);
  401.                 }
  402.                 
  403.                 if(debug)
  404.                     notify( "outTMes = %x\n", outTMes );
  405.                 
  406.                 outTPrg = NULL;
  407.                 outMes = NULL;
  408.                 outPrg = NULL;
  409.         break;
  410.         
  411.         case 2:        /* type 2: topics, programs and messages as separate files */
  412.         
  413.                 notify("Type 2:\n");
  414.                 
  415.                 strcpy( name, p->destPath );
  416.                 GetDestName( p->nameTOC, v, v->nameTOC, name,
  417.                             "Please specify destination file name for topics: " );
  418.               
  419.                   if( (outTMes = fopen( name,"w")) == NULL )
  420.                   {
  421.                     notify("Can't open '%s'\n", name );
  422.                       return(0);
  423.                   }
  424.               
  425.                   outTPrg = NULL;
  426.  
  427.                 if( p->Files )
  428.                 {
  429.                     strcpy( name, p->destPath );
  430.                     GetDestName( p->nameProg, v, v->nameProg, name,
  431.                                 "Please specify destination file name for programs: " );
  432.                   
  433.                       if( (outPrg = fopen( name,"w")) == NULL )
  434.                       {
  435.                         notify("Can't open '%s'\n", name );
  436.                           return(0);
  437.                       }
  438.  
  439.                 }
  440.                 
  441.                 strcpy( name, p->destPath );
  442.                 GetDestName( p->nameMess, v, v->nameMess, name,
  443.                             "Please specify destination file name for messages: " );
  444.               
  445.                   if( (outMes = fopen( name,"w")) == NULL )
  446.                   {
  447.                       notify("Can't open '%s'\n", name );
  448.                       return(0);
  449.                   }
  450.               
  451.         break;
  452.         
  453.         case 3:        /* type 3: toc + progs, toc + mes */
  454.         
  455.                 /* toc + progs files */
  456.                 
  457.                 if( p->Files )
  458.                 {
  459.                     strcpy( name, p->destPath );
  460.                     GetDestName( p->nameProg, v, v->nameProg, name,
  461.                                 "Please specify destination file name for programs: " );
  462.               
  463.                     if( (outTPrg = fopen( name,"w")) == NULL )
  464.                     {
  465.                         notify("Can't open '%s'\n", name );
  466.                         return(0);
  467.                     }
  468.                 }
  469.                 
  470.                 outPrg = NULL;
  471.                 
  472.                 /* toc + messages files */
  473.                 
  474.                 strcpy( name, p->destPath );
  475.                 GetDestName( p->nameMess, v, v->nameMess, name,
  476.                             "Please specify destination file name for messages: " );
  477.                 
  478.                 if( (outTMes = fopen( name,"w")) == NULL )
  479.                 {
  480.                     notify("Can't open '%s'\n", name );
  481.                     return(0);
  482.                 }
  483.                 
  484.                 outMes = NULL;              
  485.         break;
  486.         
  487.         default:
  488.                 notify( "Type of digest has not been specified, please check %s file.\n", PARMS);
  489.                 return(0);
  490.         break;
  491.     }
  492.  
  493.     return(1);
  494. }
  495.  
  496.  
  497. void SetUpTitle( ParsP p, VarsP v, FILE *out, char *Message )
  498. {
  499.     if( out != NULL )
  500.     {
  501.         fprintf(out,"<TITLE>Volume %d : Issue %d</TITLE>\n", v->VolNum, v->Issue);
  502.         fprintf(out,"<pre>\n\n");
  503.         fprintf(out,"<a href=index.html#issue%d-%d><img src=%sdigester.gif alt=Index></a> %s",
  504.                         v->Issue+1, v->VolNum, p->imagePath, Message);
  505.         
  506.         fprintf(out,"</pre>\n\n");
  507.         fprintf(out,"<hr>\n\n");
  508.         
  509.         /* include ad! */
  510.         
  511.         if( p->adOn==1 )
  512.         {
  513.             fputs("<BR><CENTER>",out);
  514.             fputs("<TABLE BORDER=5><TR><TD>", out);
  515.             fprintf(out, "<A HREF=%s><IMG ALT=CLICK_ME BORDER=1 SRC=%s></A>\n",
  516.                     p->adLink, p->adImage);
  517.             fputs("</TD></TR></TABLE>", out);
  518.             fputs("</CENTER><BR>", out);
  519.         }
  520.     }
  521. }
  522.  
  523. char *findALink( char *line )
  524. {
  525.     char *cptr;
  526.     
  527.     if( (cptr=strstr(line, "http://"))!=NULL )         return(cptr);
  528.     if( (cptr=strstr(line, "ftp://"))!=NULL )         return(cptr);
  529.     if( (cptr=strstr(line, "mailto:"))!=NULL )         return(cptr);
  530.     if( (cptr=strstr(line, "gopher://"))!=NULL )     return(cptr);
  531.  
  532.     return(NULL);
  533. }
  534.  
  535. void linkLine( char *line )
  536. {
  537.     char    *cptr, *bptr, tempLine[512], resultLine[512];
  538.     int        found;
  539.     
  540.     cptr = line;
  541.     resultLine[0]=0;
  542.     
  543.     do {
  544.         found=0;
  545.         bptr=cptr;
  546.         
  547.         if( (cptr=findALink(bptr))!=NULL )
  548.         {
  549.             found=1;
  550.             if(debug) puts("found URL");
  551.             strncpy(tempLine, bptr, cptr-bptr);    /* copy preceeding stuff */
  552.             tempLine[cptr-bptr]=0;
  553.             strcat(resultLine, tempLine);
  554.             bptr=cptr;
  555.             while(     (*cptr!=0) && (*cptr!='\n')        /* find delimiter */
  556.                     && ( (*cptr=='.') || (*cptr=='~') || (*cptr=='/') || (*cptr=='@') 
  557.                          || (*cptr==':') || (*cptr=='-') || (*cptr=='+') || (*cptr=='_')
  558.                          || ((*cptr>='a') && (*cptr<='z'))
  559.                          || ((*cptr>='A') && (*cptr<='Z'))
  560.                          || ((*cptr>='0') && (*cptr<='9'))
  561.                          || (*cptr=='%')
  562.                        )
  563.                  ) cptr++;
  564.             strncpy(tempLine, bptr, cptr-bptr);    /* copy link */
  565.             tempLine[cptr-bptr]=0;
  566.             strcat(resultLine, "<a href=");
  567.             strcat(resultLine, tempLine);
  568.             strcat(resultLine, ">");
  569.             strcat(resultLine, tempLine);
  570.             strcat(resultLine, "</a>");
  571.         }
  572.     } while( found );
  573.     
  574.     if( bptr==line ) return;                    /* nothing happened */
  575.     strcat( resultLine, bptr );                    /* copy rest of the line */
  576.     strcpy( line, resultLine );                    /* copy it back */
  577. }
  578.  
  579.  
  580. void filterEntities( char *line )
  581. {
  582.     char     tempLine[512];
  583.     int    l, i;
  584.     
  585.     tempLine[0]=0;
  586.     l = 0;
  587.     for(i=0; i<strlen(line); i++ )
  588.     {
  589.         if( line[i]=='<' )
  590.         {
  591.             tempLine[l++] = '&';
  592.             tempLine[l++] = 'l';
  593.             tempLine[l++] = 't';
  594.             tempLine[l++] = ';';
  595.         }
  596.         else
  597.         if( line[i]=='>' )
  598.         {
  599.             tempLine[l++] = '&';
  600.             tempLine[l++] = 'g';
  601.             tempLine[l++] = 't';
  602.             tempLine[l++] = ';';
  603.         }
  604.         else
  605.         if( line[i]=='"' )
  606.         {
  607.             tempLine[l++] = '&';
  608.             tempLine[l++] = 'q';
  609.             tempLine[l++] = 'u';
  610.             tempLine[l++] = 'o';
  611.             tempLine[l++] = 't';
  612.             tempLine[l++] = ';';
  613.         }
  614.         else
  615.         if( line[i]=='&' )
  616.         {
  617.             tempLine[l++] = '&';
  618.             tempLine[l++] = 'a';
  619.             tempLine[l++] = 'm';
  620.             tempLine[l++] = 'p';
  621.             tempLine[l++] = ';';
  622.         }
  623.         else
  624.         {
  625.             tempLine[l++] = line[i];
  626.             tempLine[l] = 0;
  627.         }
  628.     }
  629.     strcpy( line, tempLine );
  630. }
  631.  
  632.  
  633. int SkipTOC( ParsP p, VarsP v, int addInfo )
  634. {
  635.     int     found;
  636.     char    line[256];
  637.  
  638.     found = 0;
  639.     
  640.     if( strlen(p->BeginOfTopics)<1 )
  641.     {
  642.         /* don't bother with TOC */
  643.         if( strlen(p->EndOfTopics)>0 )
  644.         {
  645.             do {
  646.                 if( fgets( line, 256, inP ) != NULL )
  647.                 if(strstr( line, p->EndOfTopics ) != NULL)
  648.                 {
  649.                     if( debug )
  650.                         notify( "Found end of Topics\n");
  651.                         
  652.                     return(1);
  653.                 }
  654.             } while( !feof(inP ) );
  655.             
  656.             notify("Couldn't find the begining of the messages.\n");
  657.             notify("Please, check the %s file EOT tag.\n", PARMS);
  658.             
  659.             return(0);
  660.         }
  661.         
  662.         notify("No BOT or EOT tag in %s\n", PARMS);
  663.         
  664.         return(1);
  665.     }
  666.     
  667.     do {
  668.             if( fgets( line, 256, inP ) != NULL )
  669.             {
  670.                 if( strstr( line, p->BeginOfTopics ) != NULL )
  671.                 {
  672.                     if( debug )
  673.                         notify( "Found begin of Topics\n");
  674.                         
  675.                     found = 1;
  676.                 }
  677.                 
  678.                 if(strstr( line, p->EndOfTopics ) != NULL)
  679.                 {
  680.                     if( debug )
  681.                         notify( "Found end of Topics\n");
  682.                         
  683.                     return(1);
  684.                 }
  685.             }
  686.             else
  687.             {                    
  688.                 return(0);
  689.             }
  690.     } while( !found );
  691.  
  692.     fgets( line, 256, inP ); /* get empty line */
  693.  
  694.     /* skip TOC */
  695.     
  696.     do{
  697.         fgets( line, 256, inP );
  698.     }while( (strlen(line)>1) 
  699.             && !feof(inP)
  700.             && (strstr( line, p->EndOfTopics ) == NULL)
  701.            );
  702.  
  703.     if(debug)
  704.         notify("TOC skipped\n");
  705.  
  706.     if( strstr( line, p->EndOfTopics ) != NULL ) return(1);
  707.     
  708.     /* Now copy all lines to message files */
  709.     
  710.     if( outTMes!=NULL && addInfo==1 )
  711.         fputs( "<HR><P><PRE>", outTMes );
  712.  
  713.     if( outTPrg!=NULL && addInfo==1 )
  714.         fputs( "<HR><P><PRE>", outTPrg );
  715.     
  716.     do
  717.     {
  718.         fgets( line, 256, inP );
  719.         filterEntities(line);
  720.         if( p->URLs ) linkLine( line );
  721.         
  722.         if( outTMes!=NULL && addInfo==1 )
  723.             fputs( line, outTMes );
  724.             
  725.         if( outTPrg!=NULL && addInfo==1 )
  726.             fputs( line, outTPrg );
  727.     }
  728.     while( (strstr( line, p->EndOfTopics ) == NULL ) && !feof(inP) );
  729.  
  730.     if( outTMes!=NULL && addInfo==1 )
  731.         fputs( "</PRE>", outTMes );
  732.  
  733.     if( outTPrg!=NULL && addInfo==1 )
  734.         fputs( "</PRE>", outTPrg );
  735.     
  736.     if( feof(inP) )
  737.     {
  738.         notify( "Cannot find end of Topics phrase ... aborting\n");
  739.         return(0);
  740.     }
  741.     
  742.     if(debug)
  743.         notify("Found end of TOC\n");
  744.  
  745.     return(1);
  746. }
  747.  
  748. void DoFTPMessage( ParsP p, FILE *outP )
  749. {
  750.     int i;
  751.     char    name[20];
  752.     
  753.     fputs("\n<HR>\n<CENTER>\n", outP);
  754.     fputs("<H4>Direct FTP to mirror site</H4>", outP);
  755.     fputs("</CENTER>\n", outP);
  756.     
  757.     fprintf(outP, "Make FTP connection with: ");
  758.     strcpy( name, "/info-mac/");
  759.  
  760.     for(i=0; i<p->nSites; i++)
  761.     {
  762.         fputs( "", outP );
  763.         fprintf( outP, p->sites+i*LINELENGTH, name);
  764.     }        
  765.  
  766.     fputs( ".\n<P><HR><P>\n", outP );
  767. }
  768.  
  769. int MakeTOC(ParsP p, VarsP v, char *line)
  770. {
  771.     int        msgItem;
  772.     char    subject[80];
  773.     char    topic[200];
  774.     int        found;
  775.     
  776.     msgItem = 0;
  777.     
  778.     if( outTMes==NULL )
  779.     {
  780.         notify( "Error in making TOC, Message output file is not open (pointer NULL)\n\n");
  781.         return(0);
  782.     }
  783.         
  784.     if( outTPrg != NULL )
  785.     {
  786.         fputs( "<HR><CENTER>", outTPrg );
  787.         fputs( "<HR><CENTER>", outTMes );
  788.         fputs( "<H3>Programs: Table of Contents</H3>", outTPrg );
  789.         fputs( "<H3>Messages: Table of Contents</H3>", outTMes );
  790.         fputs( "</CENTER><HR>", outTPrg );
  791.         fputs( "</CENTER><HR>", outTMes );
  792.         fputs( "<UL>", outTPrg );
  793.         fputs( "<UL>", outTMes );
  794.     }
  795.     else
  796.     {
  797.         fputs( "<HR><CENTER>", outTMes );
  798.         fputs( "<H3>Table of Contents</H3>", outTMes );
  799.         fputs( "</CENTER><HR>", outTMes );
  800.         fputs( "<UL>", outTMes );
  801.     }
  802.     
  803.     do{
  804.         msgItem++;
  805.         
  806.         strcpy( subject, "" );        /* default */
  807.         found=0;
  808.         
  809.         fgets( line, 256, inP );
  810.         while( (strncmp( line, p->EndOfMessage, strlen(p->EndOfMessage) )!=0) &&
  811.                  (strstr( line, p->BegOfDigest ) == NULL) && 
  812.                  (strstr( line, p->EndOfDigest ) == NULL) && 
  813.                  !feof(inP) )
  814.         {
  815.             filterEntities( line );
  816.             
  817.             if( (strncmp( line, p->mFrom, strlen( p->mFrom ) )==0)
  818.                 && !found )
  819.             {
  820.                 strcpy( subject, "(NO SUBJECT)" );        /* default */
  821.                 v->whichFile[msgItem]='m';
  822.             }
  823.                 
  824.             /* find subject */
  825.             if( (strncmp( line, p->mSubject, strlen( p->mSubject ) )==0)
  826.                 && !found )
  827.             {
  828.                 strncpy( subject, line+strlen( p->mSubject ), 78);
  829.                 subject[79]=0;
  830.                 found=1;
  831.             }
  832.             
  833.             if( p->Files )
  834.             if( strstr( line, p->BegOfFile ) != NULL )
  835.             {
  836.                 if(debug)
  837.                     notify("Found file link for item %d!\n", msgItem);
  838.                 
  839.                 v->whichFile[msgItem]='p';
  840.             }
  841.             
  842.             fgets( line, 256, inP );
  843.         }    /* while not end of message */
  844.         
  845.         /* end of message, write TOC entry */
  846.  
  847.         if( subject[0]!=0 )        /* check if there is a subject anyway */
  848.         {
  849.             /* set correct icon */
  850.             if( v->whichFile[msgItem] == 'p' )
  851.                 sprintf(topic, "<IMG SRC=%sprog_topic.gif ALT=Program> ", p->imagePath);
  852.             else
  853.                 sprintf(topic, "<IMG SRC=%smsg_topic.gif ALT=Message> ", p->imagePath);
  854.             
  855.             if( !p->Buttons )
  856.                 strcpy( topic, "<LI> " );
  857.                 
  858.             switch( p->Type )
  859.             {
  860.                 case 1:
  861.                     fprintf(outTMes, "%s<a name=toc%d> </a><a href=#item%d>%s</a>\n",
  862.                                             topic, msgItem, msgItem, subject);
  863.                             
  864.                     if( p->Buttons )
  865.                         fputs( "<BR>\n", outTMes );
  866.                 break;
  867.                 
  868.                 case 2:
  869.                     if( v->whichFile[msgItem]=='m' )
  870.                         fprintf(outTMes, "%s<a name=toc%d> </a><a href=%s#item%d>%s</a>\n",
  871.                                                 topic, msgItem, v->nameMess, msgItem, subject);
  872.                     else
  873.                         fprintf(outTMes, "%s<a name=toc%d> </a><a href=%s#item%d>%s</a>\n",
  874.                                                 topic, msgItem, v->nameProg, msgItem, subject);
  875.                             
  876.                     if( p->Buttons )
  877.                         fputs( "<BR>\n", outTMes );
  878.                 break;
  879.                 
  880.                 case 3:
  881.                     if( v->whichFile[msgItem]=='m' )
  882.                     {
  883.                         fprintf(outTMes, "%s<a name=toc%d> </a><a href=#item%d>%s</a>\n",
  884.                                                 topic, msgItem, msgItem, subject);
  885.                             
  886.                         if( p->Buttons )
  887.                             fputs( "<BR>\n", outTMes );
  888.                     }
  889.                     else
  890.                     {
  891.                         fprintf(outTPrg, "%s<a name=toc%d> </a><a href=#item%d>%s</a>\n",
  892.                                                 topic, msgItem, msgItem, subject);
  893.                             
  894.                         if( p->Buttons )
  895.                             fputs( "<BR>\n", outTPrg );
  896.                     }
  897.                     
  898.                     
  899.                 break;
  900.                 
  901.                 default:
  902.                     return(0);    /* error occured: illegal type specified */
  903.                 break;
  904.                 
  905.             }
  906.         }
  907.         
  908.     }while( (strncmp( line, p->BegOfDigest, strlen(p->BegOfDigest) ) != 0) 
  909.             && (strstr( line, p->EndOfDigest ) == NULL) 
  910.                 && !feof( inP ) );
  911.                 
  912.     if( p->Type==3 )    /* make link between program and Q&A files */
  913.     {
  914.         if( !p->Buttons )
  915.         {
  916.             fprintf( outTMes, "<LI> " );
  917.             fprintf( outTPrg, "<LI> " );
  918.         }
  919.         else
  920.         {
  921.             fprintf( outTMes, "<IMG SRC=%sprog_topic.gif ALT=Program> ", p->imagePath);
  922.             fprintf( outTPrg, "<IMG SRC=%smsg_topic.gif ALT=Message> ", p->imagePath);
  923.                             
  924.         }
  925.         fprintf( outTMes, "<a href=%s>[*] PROGRAMS TABLE OF CONTENTS</a><BR>\n", v->nameProg );
  926.         fprintf( outTPrg, "<a href=%s>MESSAGES TABLE OF CONTENTS</a><BR>\n", v->nameMess );
  927.  
  928.     }
  929.  
  930.     if( outTMes!=NULL ) fputs( "</UL>\n<P>\n", outTMes );
  931.     if( outTPrg!=NULL ) fputs( "</UL>\n<P>\n", outTPrg );
  932.     
  933.  
  934.     /* write intro */
  935.     
  936.     if(p->Files)
  937.     {
  938.     switch( p->Type )
  939.     {
  940.         case 1:
  941.             DoFTPMessage( p, outTMes );
  942.         break;
  943.  
  944.         case 2:
  945.             DoFTPMessage( p, outTMes );
  946.         break;
  947.  
  948.         case 3:
  949.             DoFTPMessage( p, outTPrg );
  950.         break;
  951.     }
  952.     }
  953.     else
  954.     {
  955.         if( outTMes!=NULL)
  956.             fputs( ".\n<P><HR><P>\n", outTMes );
  957.     }
  958.  
  959.     return(1);
  960. }
  961.  
  962. int IsEmailChar( char c )
  963. {
  964.     if( (c>='a') && (c<='z') ) return(1);
  965.     if( (c>='A') && (c<='Z') ) return(1);
  966.     if( (c>='0') && (c<='9') ) return(1);
  967.     if( c=='.' ) return(1);
  968.     if( c=='_' ) return(1);
  969.     if( c=='-' ) return(1);
  970.     if( c=='%' ) return(1);
  971.     return(0);
  972. }
  973.  
  974. int FetchAddress( char *cptr, char *address )
  975. {
  976.     char *begin, *end;
  977.     
  978.     if( (begin=strstr(cptr,"@"))==NULL )
  979.     {
  980.         address[0]=0;    /* didn't find valid address */
  981.         return(0);
  982.     }
  983.     
  984.     begin--;
  985.     
  986.     /* find beginning of e-mail address */
  987.     while((begin>=cptr) && IsEmailChar(*begin)) begin--;
  988.     /* move one forward to the beginning of the address */
  989.     begin++;
  990.     
  991.     strcpy( address, begin );
  992.     
  993.     /* find end of address */
  994.     if( (end=strstr(address, "@"))==NULL )
  995.     {
  996.         /* this should never happen but just in case */
  997.         address[0]=0;
  998.         return(0);
  999.     }
  1000.     end++;
  1001.     while( (*end!=0) && IsEmailChar(*end) ) end++;
  1002.     /* terminate the address string */
  1003.     *end=0;
  1004.     
  1005.     return(1); /* okay! */
  1006. }
  1007.  
  1008. int DoMessages(ParsP p, VarsP v, char *line)
  1009. {
  1010.     int        msgItem;
  1011.     char    topic[200];
  1012.     char    next[200];
  1013.     char    prev[200];
  1014.     char    toc[200];
  1015.     char    post[200];
  1016.     char    index[200];
  1017.     char    address[256];
  1018.     FILE    *outP;
  1019.     char    name[80], *bptr, *eptr;
  1020.     int        i, pre;
  1021.     char     filteredLine[256];
  1022.     
  1023.     if( p->Buttons )
  1024.     {
  1025.         sprintf( next, "<img src=%snext.gif alt=Next>", p->imagePath );
  1026.         sprintf( prev, "<img src=%sprev.gif alt=Previous>", p->imagePath);
  1027.         sprintf( toc, "<img src=%stoc.gif alt=TOC>", p->imagePath);
  1028.         sprintf( post, "<img src=%spost.gif alt=MakeReply>", p->imagePath);
  1029.         sprintf( index, "<img src=%sdigester.gif alt=Index>", p->imagePath);
  1030.     }
  1031.     else
  1032.     {
  1033.         strcpy( next, "Next" );
  1034.         strcpy( prev, "Previous" );
  1035.         strcpy( toc, "Table of Contents" );
  1036.         strcpy( post, "Select Message for Posting" );
  1037.         strcpy( index, "Back to INDEX" );
  1038.     }
  1039.     
  1040.     msgItem = 0;
  1041.  
  1042.     /* do messages */
  1043.     
  1044.     do{
  1045.         msgItem++;
  1046.  
  1047.         /* choose destination file */        
  1048.  
  1049.         switch( p->Type )
  1050.         {
  1051.             case 1:
  1052.                 outP = outTMes;
  1053.             break;
  1054.             
  1055.             case 2:
  1056.                 if( (v->whichFile[msgItem]=='m') || (outPrg==NULL) )
  1057.                     outP = outMes;
  1058.                 else
  1059.                     outP = outPrg;
  1060.             break;
  1061.             
  1062.             case 3:
  1063.                 if( (v->whichFile[msgItem]=='m')  || (outTPrg==NULL) )
  1064.                     outP = outTMes;
  1065.                 else
  1066.                     outP = outTPrg;
  1067.             break;
  1068.         }
  1069.         
  1070.         if( outP == NULL )
  1071.         {
  1072.             notify("Output file not open!!\n");
  1073.             return(0);
  1074.         }
  1075.  
  1076.         /* label the thing */
  1077.         fprintf( outP, "<a name=item%d> </a> ", msgItem);
  1078.         
  1079.         /* write navigation panel */
  1080.         if( v->whichFile[msgItem]!='0' )
  1081.         switch( p->Type )
  1082.         {
  1083.             case 1:
  1084.                 fprintf( outP, "<a href=#item%d>%s</a> ", msgItem+1, next);
  1085.                 if( msgItem>1) fprintf( outP, "<a href=#item%d>%s</a> ", msgItem-1, prev );
  1086.                 fprintf( outP, "<a href=#toc%d>%s</a> ", msgItem, toc);
  1087.                 if(p->Mail) fprintf( outP, "<a href=%spost-send?%d,%s>%s</a> ", 
  1088.                                             p->scriptPath, msgItem, v->nameAll, post);
  1089.             break;
  1090.  
  1091.             case 2:
  1092.                 if(v->whichFile[msgItem+1]!='0') 
  1093.                 {
  1094.                     if( v->whichFile[msgItem+1]!=v->whichFile[msgItem])
  1095.                     {
  1096.                         if( v->whichFile[msgItem+1]=='m' )
  1097.                             fprintf( outP, "<a href=%s#item%d>%s</a> ", 
  1098.                                         v->nameMess, msgItem+1, next);
  1099.                         else
  1100.                             fprintf( outP, "<a href=%s#item%d>%s</a> ", 
  1101.                                         v->nameProg, msgItem+1, next);
  1102.                     }
  1103.                     else
  1104.                         fprintf( outP, "<a href=#item%d>%s</a> ", msgItem+1, next);
  1105.                 }
  1106.                 
  1107.                 if( msgItem>1 && (v->whichFile[msgItem-1]!='0') )
  1108.                 {
  1109.                     if( v->whichFile[msgItem-1]!=v->whichFile[msgItem] )
  1110.                     {
  1111.                         if( v->whichFile[msgItem-1]=='m' )
  1112.                             fprintf( outP, "<a href=%s#item%d>%s</a> ", 
  1113.                                                 v->nameMess, msgItem-1, prev);
  1114.                         else
  1115.                             fprintf( outP, "<a href=%s#item%d>%s</a> ", 
  1116.                                                 v->nameProg, msgItem-1, prev);
  1117.                     }
  1118.                     else 
  1119.                         fprintf( outP, "<a href=#item%d>%s</a> ", msgItem-1, prev);
  1120.                 }
  1121.  
  1122.                 fprintf( outP, "<a href=%s#toc%d>%s</a> ", v->nameTOC, msgItem, toc);
  1123.  
  1124.                 if( p->Mail )
  1125.                     if( v->whichFile[msgItem]=='m' )
  1126.                         fprintf( outP, "<a href=%spost-send?%d,%s>%s</a> ",
  1127.                                          p->scriptPath, msgItem, v->nameMess, post);
  1128.                     else
  1129.                         fprintf( outP, "<a href=%spost-send?%d,%s>%s</a> ",
  1130.                                          p->scriptPath, msgItem, v->nameProg, post);
  1131.  
  1132.             break;
  1133.  
  1134.             case 3:
  1135.                 if(v->whichFile[msgItem+1]!='0') 
  1136.                 {
  1137.                     if(v->whichFile[msgItem+1]!=v->whichFile[msgItem] )
  1138.                     {
  1139.                         if( v->whichFile[msgItem+1]=='m' )
  1140.                             fprintf( outP, "<a href=%s#item%d>%s</a> ", 
  1141.                                         v->nameMess, msgItem+1, next);
  1142.                         else
  1143.                             fprintf( outP, "<a href=%s#item%d>%s</a> ", 
  1144.                                         v->nameProg, msgItem+1, next);
  1145.                     }
  1146.                     else
  1147.                         fprintf( outP, "<a href=#item%d>%s</a> ", msgItem+1, next);
  1148.                 }
  1149.                 
  1150.                 if( (msgItem>1) && (v->whichFile[msgItem-1]!='0') ) 
  1151.                 {
  1152.                     if( v->whichFile[msgItem-1]!=v->whichFile[msgItem] )
  1153.                     {
  1154.                         if( v->whichFile[msgItem-1]=='m' )
  1155.                             fprintf( outP, "<a href=%s#item%d>%s</a> ", 
  1156.                                                 v->nameMess, msgItem-1, prev);
  1157.                         else
  1158.                             fprintf( outP, "<a href=%s#item%d>%s</a> ", 
  1159.                                                 v->nameProg, msgItem-1, prev);
  1160.                     }
  1161.                     else 
  1162.                         fprintf( outP, "<a href=#item%d>%s</a> ", msgItem-1, prev);
  1163.                 }
  1164.  
  1165.                 fprintf( outP, "<a href=#toc%d>%s</a> ", msgItem, toc);
  1166.  
  1167.                 if( p->Mail )
  1168.                     if( v->whichFile[msgItem]=='m' )
  1169.                         fprintf( outP, "<a href=%spost-send?%d,%s>%s</a> ",
  1170.                                          p->scriptPath, msgItem, v->nameMess, post);
  1171.                     else
  1172.                         fprintf( outP, "<a href=%spost-send?%d,%s>%s</a> ",
  1173.                                          p->scriptPath, msgItem, v->nameProg, post);
  1174.  
  1175.             break;
  1176.         }
  1177.  
  1178.         if( v->whichFile[msgItem]!='0' )
  1179.         fprintf( outP, "<a href=index.html#issue%d-%d>%s</a>\n\n", 
  1180.                                 v->Issue+1, v->VolNum, index);
  1181.  
  1182.         /* end of navigation bar, now do the message */
  1183.  
  1184.         fputs( "\n<PRE>", outP);
  1185.         pre=1;
  1186.         
  1187.         fgets( line, 256, inP );
  1188.         while( (strncmp( line, p->EndOfMessage, strlen(p->EndOfMessage) )!=0) &&
  1189.                  (strstr( line, p->BegOfDigest ) == NULL) && 
  1190.                  (strstr( line, p->EndOfDigest ) == NULL) && 
  1191.                  !feof(inP) )
  1192.         {
  1193.  
  1194.             if( v->whichFile[msgItem]!='0' )
  1195.             {
  1196.                 strcpy( filteredLine, line );
  1197.                 filterEntities( filteredLine );
  1198.                 if( p->URLs ) linkLine( filteredLine );
  1199.     
  1200.                 /* find Subject, Date or From */
  1201.                 if( (strncmp( line, p->mSubject, strlen( p->mSubject ) )==0) ||
  1202.                      (strncmp( line, p->mDate, strlen( p->mDate ) )==0) ||
  1203.                      (strncmp( line, p->mFrom, strlen( p->mFrom ) )==0) ||
  1204.                      (strncmp( line, p->mTo, strlen( p->mTo ) )==0)
  1205.                   )
  1206.                 {
  1207.                     if( pre ) fprintf( outP, "</PRE>");
  1208.                     pre=0;
  1209.                     if( (strncmp( line, p->mFrom, strlen( p->mFrom ) )==0) && p->MURLs )
  1210.                     {
  1211.                         if( FetchAddress( line+strlen( p->mFrom ), address ) )
  1212.                         {
  1213.                             fprintf( outP, "<a href=mailto:%s>%s</a><BR>\n", 
  1214.                                                 address, filteredLine );
  1215.                         }
  1216.                         else
  1217.                         {
  1218.                             fprintf( outP, "%s<BR>\n", filteredLine );
  1219.                         }
  1220.                         
  1221.                     }
  1222.                     else if( (strncmp( line, p->mTo, strlen( p->mTo ) )==0)  && p->MURLs )
  1223.                     {
  1224.                         if( FetchAddress( line+strlen( p->mTo ), address ) )
  1225.                         {
  1226.                             fprintf( outP, "%s<a href=mailto:%s>%s</a><BR>\n", 
  1227.                                             address, filteredLine );
  1228.                         }
  1229.                         else
  1230.                         {
  1231.                             fprintf( outP, "%s<BR>\n", filteredLine );
  1232.                         }
  1233.  
  1234.                     }
  1235.                     else
  1236.                     {
  1237.                         fprintf( outP, "%s\n<BR>\n", filteredLine);
  1238.                     }
  1239.                 }
  1240.                 else
  1241.                 {
  1242.                     if( !pre ) fprintf( outP, "<PRE>");
  1243.                     pre=1;
  1244.                     
  1245.                     fputs(filteredLine, outP);
  1246.     
  1247.                     /* check for begin of file */
  1248.                     
  1249.                     if( (strstr( line, p->BegOfFile ) != NULL) && p->Files )
  1250.                     {
  1251.                         if(debug)
  1252.                             notify("Found file link for item %d!\n", msgItem);
  1253.                     
  1254.                         bptr=strstr( line, p->RootPath );
  1255.                         eptr=strstr( line, p->EndOfFile );
  1256.     
  1257.                         if( bptr!=NULL && eptr!=NULL )
  1258.                         {
  1259.                             strncpy(name, bptr, eptr-bptr);
  1260.                             name[eptr-bptr]=0;
  1261.                     
  1262.                             fprintf( outP, "\n</pre>\nFetch from " );
  1263.     
  1264.     
  1265.                             for(i=0; i<p->nSites; i++)
  1266.                             {
  1267.                                 fprintf( outP, "\n");
  1268.                                 fprintf( outP, p->sites+i*LINELENGTH, name);
  1269.                             }        
  1270.     
  1271.                             fprintf( outP, ".\n<pre>\n" );
  1272.                         }
  1273.                         else
  1274.                         {
  1275.                             notify("Failed to make link, sorry :(\n");
  1276.                         }
  1277.                     }
  1278.                 }
  1279.             }
  1280.             fgets( line, 256, inP );
  1281.         }    /* while not end of message */
  1282.         
  1283.         fputs("</PRE>\n<HR>", outP );
  1284.         
  1285.     } while( (strncmp( line, p->BegOfDigest, strlen(p->BegOfDigest) ) != 0) 
  1286.                 && (strstr( line, p->EndOfDigest ) == NULL) 
  1287.                 && !feof( inP )
  1288.             );
  1289.  
  1290.     /* write last navigation panel */
  1291.     
  1292.     msgItem++;
  1293.     
  1294.     /* label the thing */
  1295.     fprintf( outP, "<a name=item%d> </a> ", msgItem);
  1296.  
  1297.     if( debug )
  1298.         notify( "Doing Message %d ...\n", msgItem );
  1299.     
  1300.     switch( p->Type )
  1301.     {
  1302.         case 1:
  1303.             if( msgItem>1) fprintf( outP, "<a href=#item%d>%s</a> ", msgItem-1, prev);
  1304.             fprintf( outP, "<a href=#toc1>%s</a> ", toc);
  1305.         break;
  1306.     
  1307.         case 2:
  1308.             fprintf( outP, "<a href=%s#item%d>%s</a> ", 
  1309.                                 v->nameMess, msgItem-1, prev);
  1310.     
  1311.             fprintf( outP, "<a href=%s#toc1>%s</a> ", v->nameMess, toc);
  1312.         break;
  1313.     
  1314.         case 3:
  1315.             fprintf( outP, "<a href=#item%d>%s</a> ", msgItem-1, prev);
  1316.             fprintf( outP, "<a href=#toc1>%s</a> ", toc);
  1317.         break;
  1318.     }
  1319.     
  1320.     fprintf( outP, "<a href=index.html#issue%d-%d>%s</a>\n\n", 
  1321.                             v->Issue+1, v->VolNum, index);
  1322.     
  1323.     notify( "Messages done.\n");
  1324.  
  1325.     if( (strncmp( line, p->BegOfDigest, strlen(p->BegOfDigest) ) == 0) )
  1326.     {
  1327.         notify("Found new begin of digest...\n");
  1328.         notify("Please, only use one digest per file.\n");
  1329.         notify("This version of DIGESTER does not work with multiple digests files.\n");
  1330.     }
  1331.  
  1332.  
  1333.     return(1);
  1334. }
  1335.  
  1336. #define MAIL "A.C.vanderHam@ET.TUDelft.NL"
  1337.  
  1338. void WriteTrailer( FILE *outP )
  1339. {
  1340.  
  1341.     fputs("<p><hr><p>\n", outP);
  1342.     fprintf( outP,"HTML file created by <a href=%sAboutDigester.html>%s</a><p>\n"
  1343.                     , DIGWHERE, DIGESTER);
  1344.     fprintf( outP, "The Home of the HyperDigest is at: <a href=%sindex.html>%sindex.html</a>.<p>\n"
  1345.                     , DIGWHERE, DIGWHERE );
  1346.     fprintf(outP,"Digester developed by: <a href=%s>André C. van der Ham</a><p>\n", DRE);
  1347.     fputs("<address>\n", outP);
  1348.     fprintf( outP, "Send bug reports, questions, etc. to: <A HREF=MAILTO:%s>%s</A><p>\n", MAIL, MAIL);
  1349.     fputs("</address>\n", outP);    
  1350. }
  1351.  
  1352.  
  1353. /***************************************
  1354.  
  1355.     Parse one digest at a time
  1356.     returns 1 if there is still data left after the end-of-digest phrase
  1357.     
  1358. */
  1359.  
  1360. void ParseOne( ParsP p, char *digestName )
  1361. {
  1362.     char    line[512];
  1363.     char    name[256];
  1364.     int        i;
  1365.     struct Vars    v;
  1366.         
  1367.     for(i=0; i<512; i++)                        /* init destination of all messages to nowhere */
  1368.         v.whichFile[i]='0';
  1369.     
  1370.     /* initialize all file pointers */
  1371.     
  1372.     outTPrg =    NULL;
  1373.     outTMes =    NULL;
  1374.     outPrg  =    NULL;
  1375.     outMes  =    NULL;
  1376.  
  1377.     /*  B E G I N   O F   P A S S  1 */
  1378.  
  1379.     notify("PASS1: '%s'...\n", digestName);
  1380.  
  1381.     if( (inP = fopen( digestName, "r" )) == NULL )
  1382.     {
  1383.         notify("Cannot open '%s'\n", digestName);
  1384.         notify("Please make sure '%s' is in the same folder as Digester.\n", digestName);
  1385.         return;
  1386.     }
  1387.     
  1388.     notify("Parsing...\n");
  1389.             
  1390.     if( findHeader( p, &v, line, 1 )==0 )    /* set-up header */
  1391.         return;
  1392.  
  1393.     if(debug)
  1394.         notify("Title found\n");
  1395.  
  1396.     if( SetUpFiles( p, &v )==0 )    /* set-up output files */
  1397.     {
  1398.         if( outTPrg!=NULL ) fclose( outTPrg );
  1399.         if( outTMes!=NULL ) fclose( outTMes );
  1400.         if( outPrg!=NULL )  fclose( outPrg );
  1401.         if( outMes!=NULL )  fclose( outMes );
  1402.         if( inP!=NULL )     fclose( inP );
  1403.         return;
  1404.     }
  1405.     
  1406.     if( debug )
  1407.     {
  1408.         notify( "outTPrg = %x\n", outTPrg );
  1409.         notify( "outTMes = %x\n", outTMes );
  1410.         notify( "outPrg = %x\n", outPrg );
  1411.         notify( "outMes = %x\n", outMes );
  1412.     }
  1413.     
  1414.  
  1415.     if( outTPrg!=NULL )
  1416.         SetUpTitle( p, &v, outTPrg, line );
  1417.  
  1418.     if( outTMes!=NULL )
  1419.         SetUpTitle( p, &v, outTMes, line );
  1420.  
  1421.     if( SkipTOC( p, &v, 0 ) == 0 )
  1422.     {
  1423.         if( outTPrg!=NULL ) fclose( outTPrg );
  1424.         if( outTMes!=NULL ) fclose( outTMes );
  1425.         if( outPrg!=NULL )  fclose( outPrg );
  1426.         if( outMes!=NULL )  fclose( outMes );
  1427.         if( inP!=NULL )     fclose( inP );
  1428.         return;
  1429.     }
  1430.     
  1431.     if( MakeTOC( p, &v, line )==0 )
  1432.     {
  1433.         if( outTPrg!=NULL ) fclose( outTPrg );
  1434.         if( outTMes!=NULL ) fclose( outTMes );
  1435.         if( outPrg!=NULL )  fclose( outPrg );
  1436.         if( outMes!=NULL )  fclose( outMes );
  1437.         return;
  1438.     }
  1439.  
  1440.     fclose( inP );
  1441.  
  1442.     /*  E N D   O F   P A S S  1 */
  1443.     
  1444.     notify("PASS2: '%s'...\n", digestName);
  1445.     
  1446.     if( (inP = fopen( digestName, "r" )) == NULL )
  1447.     {
  1448.         notify("Cannot open '%s',\n");
  1449.         return;
  1450.     }
  1451.     
  1452.     notify("Parsing...\n");
  1453.             
  1454.     if( findHeader( p, &v, line, 0 )==0 )    /* set-up header */
  1455.         return;
  1456.  
  1457.     if(debug)
  1458.         notify("Title found\n");
  1459.     
  1460.  
  1461.     if( outTPrg!=NULL )
  1462.         fputs("<CENTER><a href=index.html>Take me back to the INDEX, please.</a></CENTER><BR>"
  1463.                 , outTPrg );
  1464.  
  1465.     if( outTMes!=NULL )
  1466.         fputs("<CENTER><a href=index.html>Take me back to the INDEX, please.</a></CENTER><BR>"
  1467.                 , outTMes );
  1468.  
  1469.     if( SkipTOC( p, &v, 1 ) == 0 )
  1470.     {
  1471.         if( outTPrg!=NULL ) fclose( outTPrg );
  1472.         if( outTMes!=NULL ) fclose( outTMes );
  1473.         if( outPrg!=NULL )  fclose( outPrg );
  1474.         if( outMes!=NULL )  fclose( outMes );
  1475.         if( inP!=NULL )     fclose( inP );
  1476.         return;
  1477.     }
  1478.  
  1479.     if( DoMessages( p, &v, line )==0 )
  1480.     {
  1481.         if( outTPrg!=NULL ) fclose( outTPrg );
  1482.         if( outTMes!=NULL ) fclose( outTMes );
  1483.         if( outPrg!=NULL )  fclose( outPrg );
  1484.         if( outMes!=NULL )  fclose( outMes );
  1485.         if( inP!=NULL )     fclose( inP );
  1486.         return;
  1487.     }
  1488.     
  1489.     if(debug)
  1490.         notify("End of digest found...\n");
  1491.  
  1492.     if( outTPrg!=NULL ) 
  1493.     {
  1494.         WriteTrailer(outTPrg);
  1495.         fclose(outTPrg);
  1496.     }
  1497.     
  1498.     if( outTMes!=NULL ) 
  1499.     {
  1500.         WriteTrailer(outTMes);
  1501.         fclose(outTMes);
  1502.     }
  1503.     
  1504.     if( outPrg!=NULL ) 
  1505.     {
  1506.         WriteTrailer(outPrg);
  1507.         fclose(outPrg);
  1508.     }
  1509.     
  1510.     if( outMes!=NULL ) 
  1511.     {
  1512.         WriteTrailer(outMes);
  1513.         fclose(outMes);
  1514.     }
  1515.     
  1516.     notify("file closed.\n");
  1517.  
  1518. #ifdef __THINK__
  1519.     SetUpAllFinderInfo( p, &v );
  1520. #endif
  1521. }
  1522.  
  1523. int HandleArgs( ParsP p, int num_args, char *arg_strings[], char *digestName, char *parsName )
  1524. {
  1525.     int i;
  1526.     
  1527.     strcpy( parsName, PARMS);
  1528.     
  1529.     if( num_args<2 )
  1530.     {
  1531.         notify("You can also start Digester from the command line.\n");
  1532.         notify("%s <filename> <b> <2> <3> <p> <f=digest.par>\n", arg_strings[0]);
  1533.         notify("b: use fancy buttons and icons.\n");
  1534.         notify("2: split up file in 2 parts\n");
  1535.         notify("3: split up file in 3 parts\n");
  1536.         notify("p: enable post reply.\n");
  1537.         notify("f=: alternative parameters file.\n");
  1538.     }
  1539.     else
  1540.     {
  1541.         p->Type=1;
  1542.         p->Buttons=0;
  1543.         p->Mail=0;
  1544.         
  1545.         strcpy( digestName, arg_strings[1] );
  1546.         
  1547.         for(i=2; i<num_args; i++)
  1548.         {
  1549.             switch( (arg_strings[i])[0] )
  1550.             {
  1551.                 case 'b':
  1552.                     p->Buttons=1;
  1553.                     notify("Buttons on!\n");
  1554.                 break;
  1555.                 
  1556.                 case '3':
  1557.                     p->Type=2;
  1558.                     notify("Split into 3 files!\n");
  1559.                 break;
  1560.                 
  1561.                 case '2':
  1562.                     p->Type=3;
  1563.                     notify("Split into 2 files!\n");
  1564.                 break;
  1565.                 
  1566.                 case 'p':
  1567.                     p->Mail=1;
  1568.                     notify("Enable post reply.\n");
  1569.                 break;
  1570.  
  1571.                 case 'f':
  1572.                     if( ((arg_strings[i])[1]=='=') && (strlen(arg_strings[i])>2) )
  1573.                     {
  1574.                         strcpy( parsName, (arg_strings[i]+2) );
  1575.                     }
  1576.                 break;
  1577.  
  1578.                 default:
  1579.                     notify("Usage: %s <filename> <b> <2> <3> <p>\n", arg_strings[0]);
  1580.                     notify("b: use fancy buttons and icons.\n");
  1581.                     notify("2: split up file in 2 parts\n");
  1582.                     notify("3: split up file in 3 parts\n");
  1583.                     notify("p: enable post reply.\n");
  1584.                     return(0);
  1585.             }
  1586.         }
  1587.     }
  1588.     
  1589.     return(1);
  1590. }
  1591.  
  1592. int GetSites( ParsP p )
  1593. {
  1594.     char    line[256];
  1595.     FILE    *sitesP;
  1596.     int        i;
  1597.     
  1598.     notify("\nGetting file of sites...\n");
  1599.     
  1600.     if((sitesP=fopen(p->sitesFile,"r"))==NULL)
  1601.     {
  1602.         notify("Can't open file sites file.\n");
  1603.         return(0);
  1604.     }
  1605.     
  1606.     p->nSites=atoi(fgets( line, 256, sitesP));
  1607.     
  1608.     if((p->sites=malloc(p->nSites*LINELENGTH))==NULL)
  1609.     {
  1610.         notify("Out of memory error...\n");
  1611.         return(0);
  1612.     }
  1613.     
  1614.     for( i=0; i<p->nSites; i++ )
  1615.         fgets( i*LINELENGTH+p->sites, LINELENGTH, sitesP);
  1616.     
  1617.     fclose(sitesP);
  1618.     
  1619.     return(1);
  1620. }
  1621.  
  1622. void convertCodes( char *line )
  1623. {
  1624.     char     tempLine[256];
  1625.     int    l, i;
  1626.     
  1627.     tempLine[0]=0;
  1628.     l = 0;
  1629.     for(i=0; i<strlen(line); i++ )
  1630.     {
  1631.         if( line[i]=='\\' )
  1632.         {
  1633.             tempLine[l++] = line[i]-'a'+1;
  1634.             tempLine[l] = 0;
  1635.         }        
  1636.         else
  1637.         {
  1638.             tempLine[l++] = line[i];
  1639.             tempLine[l] = 0;
  1640.         }
  1641.     }
  1642.     strcpy( line, tempLine );
  1643. }
  1644.  
  1645. void checkPar( char *line, char *token, char *par, int max )
  1646. {
  1647.     char *bptr, *eptr;
  1648.     
  1649.     if( strncmp( line, token, strlen(token) )!=0 ) return;
  1650.     
  1651.     bptr = line+strlen(token);
  1652.     
  1653.     while( (*bptr!='"') && (*bptr!=0) ) bptr++;        /* find first quote */
  1654.     
  1655.     if(*bptr==0)
  1656.     {
  1657.         notify("Failed to read parameter value of '%s'\n", token);
  1658.         return;
  1659.     }
  1660.     
  1661.     eptr=bptr+1;
  1662.  
  1663.     while( (*eptr!='"') && (*eptr!=0) ) eptr++;        /* find second quote */
  1664.     
  1665.     if(*eptr==0)
  1666.     {
  1667.         notify("Failed to read parameter string of '%s'\n", token);
  1668.         return;
  1669.     }
  1670.     
  1671.     if((eptr-bptr)>max)
  1672.     {
  1673.         notify("Parameter string of '%s' too long\n", token);
  1674.         return;
  1675.     }
  1676.  
  1677.     *eptr=0;    /* terminate the string */
  1678.     
  1679.     strcpy( par, bptr+1 );    /* copy the parameter string */
  1680.     
  1681.     if( debug )
  1682.         notify( "Parameter '%s': %s\n", token, par );
  1683.         
  1684.     convertCodes( par );
  1685. }
  1686.  
  1687. void checkParNum( char *line, char *token, int *par )
  1688. {
  1689.     if( strncmp( line, token, strlen(token) )!=0 ) return;
  1690.  
  1691.     if( sscanf( line+strlen(token), "%d", par )!=1 )
  1692.         notify("Failed to get parameter '%s'.\n", token);    
  1693.     else
  1694.     if( debug )
  1695.         notify("Parameter '%s': %d\n", token, *par );
  1696. }
  1697.  
  1698. void InitPars( ParsP p )
  1699. {
  1700.     /* initialize all struct variables */
  1701.     strcpy( p->adLink, "" );
  1702.     strcpy( p->adImage, "" );
  1703.     p->adOn=0;
  1704.     
  1705.     strcpy( p->scriptPath,     "/vdham-bin/" );
  1706.     strcpy( p->sitesFile,     "sites.asc" );
  1707.     strcpy( p->imagePath, "" );
  1708.     strcpy( p->destPath,     "" );
  1709.     strcpy( p->Ftype, "TEXT" );
  1710.     strcpy( p->Fcreator, "MOSS" );
  1711.  
  1712.     strcpy( p->DigestName,     "infomac.txt" );
  1713.     strcpy( p->nameAll,     "IM%d-%d.html" );
  1714.     strcpy( p->nameTOC,     "IMt%d-%d.html" );
  1715.     strcpy( p->nameProg,     "IMp%d-%d.html" );
  1716.     strcpy( p->nameMess,     "IMm%d-%d.html" );
  1717.     
  1718.     strcpy( p->BegOfDigest, "Info-Mac Digest      " );
  1719.     strcpy( p->Volume,         "Volume" );
  1720.     strcpy( p->Issue,         "Issue" );
  1721.     strcpy( p->Date,         "" );
  1722.     
  1723.     strcpy( p->EndOfDigest, "End of Info-Mac Digest" );
  1724.     strcpy( p->BeginOfTopics, "Today's Topics:" );
  1725.     strcpy( p->EndOfTopics, "----------------------------------------------------------------------" );
  1726.     strcpy( p->EndOfMessage, "------------------------------\n" );
  1727.     
  1728.     strcpy( p->RootPath,     "/info-mac/" );
  1729.     strcpy( p->BegOfFile,     "[Archived as " );
  1730.     strcpy( p->EndOfFile,     ";" );
  1731.     
  1732.     p->Type        = 1;
  1733.     p->Buttons    = 1;
  1734.     p->Mail     = 1;
  1735.     p->Files     = 1;
  1736.     p->URLs     = 1;
  1737.     p->MURLs     = 0;
  1738.  
  1739.     p->sites     = NULL;
  1740.     p->nSites     = 0;
  1741.  
  1742.     strcpy( p->mFrom, "From: ");
  1743.     strcpy( p->mTo, "To: ");
  1744.     strcpy( p->mDate, "Date: ");
  1745.     strcpy( p->mSubject, "Subject: ");
  1746. }
  1747.  
  1748. int GetParameters( ParsP p, char *name, int *promptP )
  1749. {
  1750.     FILE     *inP;
  1751.     char    *cptr;
  1752.     char    line[256];
  1753.     
  1754.     notify("Using parameter file: '%s'.\n", name );
  1755.     
  1756.     if( (inP = fopen(name, "r")) == NULL )
  1757.     {
  1758.         notify("Cannot open '%s', using default values\n", name);
  1759.         return(1);
  1760.     }
  1761.     
  1762.     while( !feof(inP) )
  1763.     {
  1764.         fgets( line, 256, inP );
  1765.         
  1766.         if( (cptr=strstr(line, "#")) != NULL )    /* mask comments */
  1767.         {
  1768.             *cptr=0;
  1769.         }
  1770.         
  1771.         if(strlen(line)>2)
  1772.         {
  1773.             checkPar( line, "ADLINK", p->adLink, 80 );
  1774.             checkPar( line, "ADIMAGE", p->adImage, 80 );
  1775.             checkParNum( line, "ADON", &(p->adOn));
  1776.  
  1777.             checkPar( line, "SCRIPT", p->scriptPath,80 );
  1778.             checkPar( line, "SITE", p->sitesFile,20 );
  1779.             checkPar( line, "PATH", p->destPath,80 );
  1780.             checkPar( line, "IMAGES", p->imagePath,80 );
  1781.             checkPar( line, "FTYPE", p->Ftype,6 );
  1782.             checkPar( line, "FCREAT", p->Fcreator, 6 );
  1783.     
  1784.             checkPar( line, "DIGNAM", p->DigestName,20);
  1785.             checkPar( line, "NAMA", p->nameAll,20);
  1786.             checkPar( line, "NAMT", p->nameTOC,20);
  1787.             checkPar( line, "NAMP", p->nameProg,20);
  1788.             checkPar( line, "NAMM", p->nameMess,20);
  1789.     
  1790.             checkPar( line, "BOD", p->BegOfDigest,80);
  1791.             checkPar( line, "VOL", p->Volume,80);
  1792.             checkPar( line, "ISS", p->Issue,80);
  1793.             checkPar( line, "DAT", p->Date,20);
  1794.     
  1795.             checkPar( line, "EOD", p->EndOfDigest,80);
  1796.             checkPar( line, "BOT", p->BeginOfTopics,80);
  1797.             checkPar( line, "EOT", p->EndOfTopics,80);
  1798.             checkPar( line, "EOM", p->EndOfMessage,80);
  1799.     
  1800.             checkPar( line, "RTD", p->RootPath,20);
  1801.             checkPar( line, "BOF", p->BegOfFile,40);
  1802.             checkPar( line, "EOF", p->EndOfFile,20);
  1803.             
  1804.             checkPar( line, "MDATE", p->mDate, 20 );
  1805.             checkPar( line, "MFROM", p->mFrom, 20 );
  1806.             checkPar( line, "MTO", p->mTo, 20 );
  1807.             checkPar( line, "MSUBJECT", p->mSubject, 20 );
  1808.             
  1809.     
  1810.             checkParNum( line, "TYP", &(p->Type));
  1811.             checkParNum( line, "BUT", &(p->Buttons));
  1812.             checkParNum( line, "MAI", &(p->Mail));
  1813.             checkParNum( line, "FIL", &(p->Files));
  1814.             checkParNum( line, "URL", &(p->URLs));
  1815.             checkParNum( line, "MURL", &(p->MURLs));
  1816.             checkParNum( line, "DEBUG", &debug);
  1817.             checkParNum( line, "PROMPT", promptP);
  1818.         }
  1819.     }
  1820.     return(0);
  1821. }
  1822.  
  1823. int main( int num_args, char *arg_strings[] )
  1824. {
  1825.     char    digestName[80], answer[80], parsName[80];
  1826.     char    line[256];
  1827.     struct Pars    p;
  1828.     int        nopars;
  1829.     int        prompt=1;
  1830.  
  1831.     InitPars( &p );
  1832.     
  1833.     if( HandleArgs( &p, num_args, arg_strings, digestName, parsName )==0 )
  1834.         return(1);
  1835.  
  1836.     nopars=GetParameters( &p, parsName, &prompt );
  1837.  
  1838.     if( p.Files )
  1839.     {
  1840.         if( GetSites( &p )==0 )
  1841.             return(1);
  1842.     }
  1843.  
  1844.  
  1845.     notify("\n\n*** D I G E S T E R ***\n\n");
  1846.     notify("by Andre' C. van der Ham\n\n");
  1847.     notify("This program parses info-mac digests you get by e-mail.\n");
  1848.     notify("Save the e-mail without headers and paragraph recognition (Eudora)\n");
  1849.     notify("Please, use one digest per file.\n");
  1850.     notify("Convert file to appropriate ascii format, for example: Mac->Unix\n\n");
  1851.     notify("The file can contain a number of digests.\n");
  1852.     notify("An HTML file is generated for each issue.\n");
  1853.     notify("Send bug reports, questions, etc... to:\n");
  1854.     notify("e-mail: A.C.vanderHam@ET.TUDelft.NL\n\n\n");
  1855.  
  1856.     if( num_args<2 )
  1857.     { 
  1858. #ifndef __THINK__
  1859.  
  1860.         notify("Input file (%s): ", p.DigestName);        
  1861.         gets( digestName );
  1862.         if(strlen(digestName)<2)
  1863.             strcpy( digestName, p.DigestName);
  1864. #else
  1865.         if( GetName( digestName )==0 ) return(1);
  1866. #endif
  1867.  
  1868.         if(prompt)
  1869.         {
  1870.             notify("Use fancy buttons and icons (y/N): ");
  1871.             gets( answer );
  1872.         
  1873.             if( answer[0]=='y' )
  1874.                 p.Buttons=1;
  1875.             else
  1876.                 p.Buttons=0;
  1877.         
  1878.             notify("Include message selection button for reply (y/N): ");
  1879.             gets( answer );
  1880.         
  1881.             if( answer[0]=='y' )
  1882.                 p.Mail=1;
  1883.             else
  1884.                 p.Mail=0;
  1885.         
  1886.             notify("Split file into 3 separate files for topics, programs and messages (y/N): ");
  1887.             gets( answer );
  1888.         
  1889.             if( answer[0]=='y' ) 
  1890.                 p.Type=2;
  1891.             else
  1892.                 p.Type=1;
  1893.     
  1894.             notify("Split file into 2 separate files for programs and messages (y/N): ");
  1895.             gets( answer );
  1896.         
  1897.             if( answer[0]=='y' ) 
  1898.                 p.Type=3;
  1899.         }
  1900.     }
  1901.  
  1902.     ParseOne( &p, digestName );
  1903.     
  1904.     notify("Thanks for using Digester.\nHave a nice day.\n");
  1905. #ifdef __THINK__
  1906.     notify("Please press Return to continue.\n");
  1907. #endif
  1908.  
  1909.     return(0);
  1910. }